package com.online.taxi.jms.consumer.config;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.jms.config.JmsListenerContainerFactory;
import org.springframework.jms.core.JmsTemplate;

import javax.jms.Queue;
import javax.jms.Topic;

@Configuration
public class ActiveMQConfig {

  @Value("${spring.activemq.broker-url}")
  private String brokerUrl;

  @Bean
  public Queue queue() {
    return new ActiveMQQueue("ActiveMQQueue");
  }

  @Bean
  public Topic topic() {
    return new ActiveMQTopic("ActiveMQTopic");
  }

  @Bean
  public ActiveMQConnectionFactory connectionFactory(RedeliveryPolicy redeliveryPolicy) {

    ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(
        "admin",
        "admin",
        brokerUrl);
    activeMQConnectionFactory.setRedeliveryPolicy(redeliveryPolicy);
    return activeMQConnectionFactory;
  }

  /**
   * Queue模式连接注入
   */
  @Bean
  public JmsListenerContainerFactory<?> jmsListenerContainerQueue(ActiveMQConnectionFactory connectionFactory) {
    DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
    bean.setConnectionFactory(connectionFactory);

    bean.setConnectionFactory(connectionFactory);
    /**
     * 客户端手动确认，这就意味着AcitveMQ将不会自动ACK任何消息。
     * 如果一个conmuser在消费结束前没有调用message.acknowledge()确认一个消息，
     * 之后调用其他conmuser时会再次消费它，因为对于broker而言，那些尚未真正ACK的消息被视为未消费，
     * 直到它被确认。
     */
    bean.setSessionAcknowledgeMode(2);
    return bean;
  }

  /**
   * Topic模式连接注入
   * 
   * @param connectionFactory
   * @return
   */
  @Bean
  public JmsListenerContainerFactory<?> jmsListenerContainerTopic(ActiveMQConnectionFactory connectionFactory) {
    DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
    // 设置为发布订阅方式, 默认情况下使用的生产消费者方式
    bean.setPubSubDomain(true);
    bean.setConnectionFactory(connectionFactory);
    return bean;
  }

  @Bean
  public RedeliveryPolicy redeliveryPolicy() {
    RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
    // //是否在每次尝试重新发送失败后,增长这个等待时间
    // redeliveryPolicy.setUseExponentialBackOff(true);
    // //重发次数,默认为6次 这里设置为10次
    // redeliveryPolicy.setMaximumRedeliveries(10);
    // //重发时间间隔,默认为1秒
    // redeliveryPolicy.setInitialRedeliveryDelay(1);
    // //第一次失败后重新发送之前等待500毫秒,第二次失败再等待500 * 2毫秒,这里的2就是value
    // redeliveryPolicy.setBackOffMultiplier(2);
    // //是否避免消息碰撞
    // redeliveryPolicy.setUseCollisionAvoidance(false);
    // //设置重发最大拖延时间-1 表示没有拖延只有UseExponentialBackOff(true)为true时生效
    // redeliveryPolicy.setMaximumRedeliveryDelay(-1);
    return redeliveryPolicy;
  }

  @Bean
  public JmsTemplate jmsTemplate(ActiveMQConnectionFactory activeMQConnectionFactory, Queue queue) {
    JmsTemplate jmsTemplate = new JmsTemplate();
    jmsTemplate.setDeliveryMode(2);// 进行持久化配置 1表示非持久化，2表示持久化
    jmsTemplate.setConnectionFactory(activeMQConnectionFactory);
    jmsTemplate.setDefaultDestination(queue); // 此处可不设置默认，在发送消息时也可设置队列
    jmsTemplate.setSessionAcknowledgeMode(4);// 客户端签收模式
    return jmsTemplate;
  }

}